package ji

import (
	"net/http"
	"path"
)

type RouterGroup struct {
	prefix      string        //前缀
	parent      *RouterGroup  //父路由组 如果是engine 则这个属性设置为nil
	middlewares []HandlerFunc //中间件
	router      *Router       //为了拿到同一颗树
}

func (r *RouterGroup) Group(prefix string, router *Router) *RouterGroup {
	return newRouterGroup(r.prefix+prefix, r, nil, router)
}

func newRouterGroup(prefix string, parent *RouterGroup, middlewares []HandlerFunc, router *Router) *RouterGroup {
	return &RouterGroup{
		prefix:      prefix,
		parent:      parent,
		middlewares: middlewares,
		router:      router,
	}
}

func (r *RouterGroup) addRoute(method string, path string, handlerFunc HandlerFunc) {
	//router.New().AddRoute(method, r.prefix+path, handlerFunc) //todo 已解决 不同于engine的路由=>不在同一颗树上 然后访问不了！ 为了解决循环import 导致无法编译/运行 从而使用router
	r.router.AddRoute(method, r.prefix+path, handlerFunc)
}

func (r *RouterGroup) GET(path string, handlerFunc HandlerFunc) {
	r.addRoute("GET", path, handlerFunc)
}

func (r *RouterGroup) POST(path string, handlerFunc HandlerFunc) {
	r.addRoute("POST", path, handlerFunc)
}

func (r *RouterGroup) Use(middlewares ...HandlerFunc) {
	r.middlewares = append(r.middlewares, middlewares...)
}

// 创建静态处理器
// relativePath 相对路径 可能为 /static/a.txt
// fs 映射本地的目录 用于打开该目录下的文件
func (r *RouterGroup) createStaticHandler(relativePath string, fs http.FileSystem) HandlerFunc {

	absolutePath := path.Join(r.prefix, relativePath)

	fileServer := http.StripPrefix(absolutePath, http.FileServer(fs))
	// http.StripPrefix(absolutePath, http.FileServer(http.Dir("/static")))
	//					去除absolutePath前缀 建立http.FileServer(fs)的本地文件目录映射 [fs用于打开目录下的文件] 并且返回Handler [用于将文件发送至前端]
	return func(ctx *Context) {
		file := ctx.Param("filepath")
		if _, err := fs.Open(file); err != nil {
			ctx.status(http.StatusNotFound)
			return
		}
		//静态资源返回前端
		fileServer.ServeHTTP(ctx.response, ctx.request)
	}
}

// Static 用户设置静态资源映射
// r.Static("/assets", "/usr/ji/blog/static")
// 用户访问localhost:9999/assets/js/index.js，最终返回/usr/ji/blog/static/js/index.js。
func (r *RouterGroup) Static(relativePath string, root string) {
	handler := r.createStaticHandler(relativePath, http.Dir(root))
	urlPath := path.Join(relativePath, "/*filepath")
	r.GET(urlPath, handler)
}
